package engine;

import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.Random;

import com.golden.gamedev.Game;
import com.golden.gamedev.object.Sprite;
import com.golden.gamedev.object.PlayField;
import com.golden.gamedev.object.Timer;
import com.golden.gamedev.object.Background;
import com.golden.gamedev.object.SpriteGroup;
import com.golden.gamedev.object.background.TileBackground;
import com.golden.gamedev.object.background.abstraction.AbstractTileBackground;

import sprites.TDEntity;
import sprites.PacmanEnemy;
import sprites.Treasure;
import collisions.*;

/**
 * A simple tower defense game.
 * 
 * @author Alex Lee (hl69)
 */
public class TowerDefense extends Game
{

	/*
	 * Ready for distribution!
	 */
	// { distribute = true; }

	/*
	 * The game is played on a tiled board.
	 */
	public static final int ROWS = 6, COLS = 8, TILESIZE = 120;

	/*
	 * The game levels up after a certain amount of time has elapsed. As the
	 * player levels up, enemies spawn faster and faster, making the game more
	 * difficult.
	 */
	Timer levelTimer, spawnTimer;
	int currentRound = 0;
	int[] rounds = { 5000, 4000, 3000, 2000, 1000 };

	/*
	 * 
	 */
	public PlayField field;
	AbstractTileBackground background;
	TDEntity[][] map;

	/*
	 * The main sprite groups are the treasures, towers, tower projectiles,
	 * enemies, and enemy projectiles.
	 */
	public SpriteGroup TREASURES, TOWERS, TOWER_P, ENEMIES, ENEMY_P;

	/*
	 * Money can be used to build more towers. The user gets money by killing
	 * enemies.
	 */
	int money;

	Random random;

	@Override
	public void initResources()
	{
		random = new Random();

		/*
		 * Set up the background and the playfield.
		 */
		background = new TileBackground(getImages("resources/grasstile.jpg", 1, 1),
				COLS, ROWS);
		field = new PlayField(background);
		map = new TDEntity[ROWS][COLS];

		/*
		 * Initialize sprite groups.
		 */
		TREASURES = field.addGroup(new SpriteGroup("Treasures"));
		TOWERS = field.addGroup(new SpriteGroup("Towers"));
		TOWER_P = field.addGroup(new SpriteGroup("Tower Projectiles"));
		ENEMIES = field.addGroup(new SpriteGroup("Enemies"));
		ENEMY_P = field.addGroup(new SpriteGroup("Enemy Projectiles"));

		/*
		 * Add a wall of treasures that the player must defend.
		 */
		for(int i = 0; i < ROWS; i++)
		{
			TREASURES.add(new Treasure(this, 0, TILESIZE*i));
		}

		/*
		 * For debug, add one tower.
		 */
		//TOWERS.add(new sprites.WeakTower(this, TILESIZE, randomY()));
		TOWERS.add(new sprites.WeakTower(this, TILESIZE, TILESIZE*3));
		TOWERS.add(new sprites.MGTower(this, TILESIZE, TILESIZE));

		/*
		 * Start timers. Level goes up every minute; initially, enemies spawn
		 * every four seconds.
		 */
		levelTimer = new Timer(60000);
		spawnTimer = new Timer(4000);

		/*
		 * Register collision groups.
		 */
		field.addCollisionGroup(TOWER_P, ENEMIES,
				new ProjectileEnemyCollision());
		field.addCollisionGroup(ENEMIES, TOWERS, new EnemyTowerCollision());
		field.addCollisionGroup(ENEMIES, TREASURES, new EnemyTowerCollision());
	}

	@Override
	public void update(long elapsedTime)
	{
		/*
		 * Update the playfield.
		 */
		field.update(elapsedTime);

		/*
		 * Update the map.
		 */
		

		/*
		 * Update towers and enemies.
		 */
		updateTowers(elapsedTime);
		updateEnemies(elapsedTime);
		
		/*
		 * Debug: If mouse2 is pressed, spawn an enemy.
		 */
		if(bsInput.isMousePressed(MouseEvent.BUTTON3))
		{
			spawn();
		}

		/*
		 * If there are no more treasures, defeat.
		 */
		if(TREASURES.getActiveSprite() == null)
		{
			finish();
		}

		/*
		 * Quit the game if the user hits escape.
		 */
		if(keyDown(KeyEvent.VK_ESCAPE)) finish();
	}

	private void updateTowers(long elapsedTime)
	{

	}

	private void updateEnemies(long elapsedTime)
	{
		/*
		 * Spawn more enemies according to the timer.
		 */
		if(spawnTimer.action(elapsedTime)) spawn();
	}

	private void spawn()
	{
		ENEMIES.add(new PacmanEnemy(this, TILESIZE*COLS, randomY()));
	}

	private int randomX()
	{
		return TILESIZE * random.nextInt(COLS);
	}

	private int randomY()
	{
		return TILESIZE * random.nextInt(ROWS);
	}

	@Override
	public void render(Graphics2D g)
	{
		/*
		 * Render the playfield.
		 */
		field.render(g);
		
		Point tileAt = background.getTileAt(getMouseX(), getMouseY());

		/*
		 * Show how much money the user has.
		 */
		fontManager.getFont("FPS Font").drawString(g,"MONEY = " + money,
				10, 10);
	}

	public void addMoney(int amount)
	{
		money += amount;
	}

}
